package System;

import java.io.File;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import Logic.Movie;
import Logic.Rank;
import Logic.User;

public class DataManager {
	//"C:/Documents and Settings/gamsalem/workspace/Movies/movies.xml"
	//"C:/Documents and Settings/gamsalem/workspace/Movies/users.xml";
	//"C:/Documents and Settings/gamsalem/workspace/Movies/ranks.xml";
	final private String moviesXmlFile = "movies.xml";	
	final private String usersXmlFile = "users.xml";
	final private String ranksXmlFile = "ranks.xml";
	
	
	private Document moviesDocument;
	private Document usersDocument;
	private Document ranksDocument;		
	
	private Vector<Movie> movies = new Vector<Movie>();
	private Vector<User> users = new Vector<User>();
	private Vector<Rank> ranks = new Vector<Rank>();
	
	public DataManager(){
	
	}
	
	private Document loadDocument(String fileName) throws Exception{
		try {
			DocumentBuilder builder;		
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			builder = factory.newDocumentBuilder();	    	
			Document document = builder.parse(new File(fileName));
			return document;
		}
		catch(Exception ex){
			throw ex;
		}    	
	}
	

	public Vector<Movie> loadMoviesData() {			
	    Movie tmp;	    
	   // Vector<Movie> movies = new Vector<Movie>(10);
	    try {
	    	moviesDocument = loadDocument(moviesXmlFile);	    	
	        NodeList nl = moviesDocument.getElementsByTagName("movie");	        
	        int size = nl.getLength();
	        Node node;
	        for(int i=0; i<size; i++){	        	
	        	node = nl.item(i);
	            tmp = new Movie(node);
	            movies.add(tmp);
	            //System.out.println(tmp);
	        }
	        System.out.println("All movies created");
	        return movies;
	    }
	   	catch(Exception e){
	   		System.out.println("Cannot read from the movies.xml");
	   		System.out.println(e.getMessage());
	   	}
	   	return null;
	}

	public Vector<User> loadUsersData(){		
	    User tmp;	    
	    //Vector<User> users = new Vector<User>(10);
	    try {
	    	usersDocument = loadDocument(usersXmlFile);	    	
	        NodeList nl = usersDocument.getElementsByTagName("user");	        
	        int size = nl.getLength();	        
	        for(int i=0; i<size; i++){	        	
	            Node node = nl.item(i);	            
	            tmp = new User(node);
	            users.add(tmp);
	            //System.out.println(tmp);
	        }
	        System.out.println("All users created");
	        return users;
	    }
	   	catch(Exception ex){
	   		System.out.println("Cannot read from the movies.xml");
	   		System.out.println(ex.getMessage());
	   	}
	   	return null;	
	}
	
	public Vector<Rank> loadRanksData(){		
	    Rank tmp;	    
	   // Vector<User> users = new Vector<User>(10);
	    Movie tMov;
	    User tUsr;
	    try {
	    	ranksDocument = loadDocument(ranksXmlFile);	    	
	        NodeList nl = ranksDocument.getElementsByTagName("rank");	        
	        int size = nl.getLength();	        
    		NamedNodeMap attributes;    		
    		int rank;
	        for(int i=0; i<size; i++){	        	
	            Node node = nl.item(i);	            					
	    		attributes = node.getAttributes();    	
	            tMov = findMovie(attributes.getNamedItem("movie").getNodeValue());
	            tUsr = findUser(attributes.getNamedItem("user").getNodeValue());
	            rank = Integer.valueOf(attributes.getNamedItem("rank").getNodeValue());
	            if (tMov == null)
	            	System.out.println("Rank error: movie undefind");
	            else if (tUsr == null)
	            	System.out.println("Rank error: user undefind");
	            else if ((rank < 1) || (rank > 10)) 
	            	System.out.println("Rank error: rank out of range (1..10)");
	            else {
	            	//System.out.println("Here");
	            	//System.out.println(tMov);
	            	//System.out.println(tUsr);
	            	//System.out.println(rank);
	            	tmp = new Rank(tMov,tUsr,rank);
	            	ranks.add(tmp);
	            	tMov.addRank(tmp);
	            	tUsr.addRank(tmp);
	            	//System.out.println(tmp);
	            }
	        }
	        System.out.println("All ranks created");
	        return ranks;
	    }
	   	catch(Exception ex){
	   		System.out.println("Cannot read from the ranks.xml");
	   		System.out.println(ex.getMessage());
	   	}
	   	return null;	
	}
	
	private Movie findMovie(String name) {
		int size = movies.size();		
		for (int i=0; i<size; i++){		
			if (movies.get(i).getName().equals(name))
				return movies.get(i);
		}
		return null;
	}
	
	private User findUser(String username) {
		int size = users.size();		
		for (int i=0; i<size; i++){		
			if (users.get(i).getUsername().equals(username))
				return users.get(i);
		}
		return null;
	}

	public void createNewNode(Document doc, String name, String[] fields, String[] vals){		
		int size = vals.length;
		Element el = doc.createElement(name);
		for (int i=0; i<size; i++)
			el.setAttribute(fields[i],vals[i]);
		doc.getFirstChild().appendChild(el);
	}
	
	public void createNewMovieNode(Movie m){
		createNewNode(this.moviesDocument, "movie", m.getFields(), m.getVals()); 
		saveDocumentToXml(moviesDocument, moviesXmlFile);
	}
	
	public void createNewUserNode(User u) {
		createNewNode(this.usersDocument, "user", u.getFields(), u.getVals()); 
		saveDocumentToXml(usersDocument, usersXmlFile);
	}
	
	public void saveMoviesData(){
		saveDocumentToXml(moviesDocument, moviesXmlFile);
	}
	
	public void saveUsersData(){
		saveDocumentToXml(usersDocument, usersXmlFile);
	}
	
	public void createNewRankNode(Rank r) {
		createNewNode(this.ranksDocument, "rank", r.getFields(), r.getVals()); 
		saveDocumentToXml(ranksDocument, ranksXmlFile);
	}
	
	public void saveData(){
		saveDocumentToXml(moviesDocument, moviesXmlFile);
		saveDocumentToXml(usersDocument, usersXmlFile);
		saveDocumentToXml(ranksDocument, ranksXmlFile);
		
	}
	
	private void saveDocumentToXml(Document doc, String fileName){
		try{
	    	DOMSource source = new DOMSource(doc.getFirstChild());	    
	    	File file = new File(fileName);
	    	StreamResult result = new StreamResult(file);       
	    	Transformer xformer = TransformerFactory.newInstance().newTransformer();
	    	xformer.transform(source, result);
	    }
	    catch(Exception ex){
	    	System.out.println("Can't save document to xml");
	   		System.out.println(ex.getMessage());
	    }		
	}

}
